import { Inject, Provide, Init } from '@midwayjs/core';
import { BaseService, CoolCommException } from '@cool-midway/core';
import { InjectEntityModel } from '@midwayjs/typeorm';
import { In, Repository } from 'typeorm';
import { OrderCartEntity } from '../entity/cart';
import { GoodsInfoService } from '../../goods/service/info';
import { GoodsSpecService } from '../../goods/service/spec';
import { OrderGoodsEntity } from '../entity/goods';
import { OracleService } from '../../../comm/service/oracle.service';
import * as oracledb from 'oracledb';
import { GoodsInfoEntity } from '../../goods/entity/info';
import { UserInfoEntity } from '../../user/entity/info';
import { UserCertEntity } from '../../user/entity/cert.entity';

/**
 * 购物车
 */
@Provide()
export class OrderCartService extends BaseService {
  @InjectEntityModel(OrderCartEntity)
  orderCartEntity: Repository<OrderCartEntity>;

  @Inject()
  goodsInfoService: GoodsInfoService;

  @InjectEntityModel(GoodsInfoEntity)
  goodsInfoEntity: Repository<GoodsInfoEntity>;

  @InjectEntityModel(UserInfoEntity)
  userInfoEntity: Repository<UserInfoEntity>;

  @InjectEntityModel(UserCertEntity)
  userCertEntity: Repository<UserCertEntity>;

  @Inject()
  goodsSpecService: GoodsSpecService;

  @Inject()
  oracleService: OracleService;

  @Init()
  async init() {
    await super.init();
    this.setEntity(this.orderCartEntity);
  }

  /**
   * 获取商品实时库存和价格
   */
  async getGoodsBalanceAndPrice(goodsId: string, userId: string): Promise<{ stornum: number; saletaxp: number } | null> {
    const currentOracleDataSource = this.oracleService.getDataSource();
    if (!currentOracleDataSource || !currentOracleDataSource.isInitialized) {
      throw new CoolCommException('数据源不可用');
    }

    let connection: oracledb.Connection | undefined;
    try {
      const driver = currentOracleDataSource.driver as any;
      const pool = driver.pool || driver.master;
      if (!pool || typeof pool.getConnection !== 'function') {
        throw new CoolCommException('无法获取数据库连接');
      }
      
      connection = await pool.getConnection();

      // 确保输入参数为字符串类型
      const goodsIdStr = String(goodsId).trim();
      const userIdStr = String(userId).trim();
      
      const bindParams: oracledb.BindParameters = {
        DATASET: { type: oracledb.CURSOR, dir: oracledb.BIND_OUT },
        yxc_b2b_goodsid: { type: oracledb.STRING, dir: oracledb.BIND_IN, val: goodsIdStr, maxSize: 100 },
        yxc_b2b_clientid: { type: oracledb.STRING, dir: oracledb.BIND_IN, val: userIdStr, maxSize: 100 }
      };

      const result = await connection.execute<{ DATASET: oracledb.ResultSet<any> }>(
        `BEGIN YXC_B2B_SP_BALANCE_PRICE(:DATASET, :yxc_b2b_goodsid, :yxc_b2b_clientid); END;`,
        bindParams,
        { 
          outFormat: oracledb.OUT_FORMAT_OBJECT,
          autoCommit: true
        }
      );

      if (result && result.outBinds && result.outBinds.DATASET) {
        const resultSet = result.outBinds.DATASET;
        if (resultSet && typeof resultSet.getRows === 'function') {
          const rows = await resultSet.getRows();
          await resultSet.close();
          
          if (rows && rows.length > 0) {
            return {
              stornum: Number(rows[0].STORNUM || 0),
              saletaxp: Number(rows[0].SALETAXP || 0)
            };
          }
        }
      }
      
      return null;
    } catch (error) {
      console.log('获取商品库存价格失败:', error);
      throw new CoolCommException('获取商品库存价格失败');
    } finally {
      if (connection) {
        try {
          await connection.close();
        } catch (error) {
          console.error('关闭数据库连接失败:', error);
        }
      }
    }
  }

  /**
   * 检查用户经营权限
   */
  async checkBusinessPermission(userId: string, qCategory: string) {
    if (!qCategory) {
      return; // 如果商品没有质量分类，则允许添加
    }

    // userId 在这里实际上是 erpBusinessId，直接用于查询用户证书信息
    const userCerts = await this.userCertEntity.find({
      where: { erpBusinessId: userId },
      select: ['businessCont']
    });

    if (!userCerts || userCerts.length === 0) {
      throw new CoolCommException('未找到用户经营证照信息，无经营权限');
    }

    // 合并所有证书的经营范围并去重
    const allBusinessScopes = new Set<string>();
    for (const cert of userCerts) {
      if (cert.businessCont) {
        const scopes = cert.businessCont.split(',');
        scopes.forEach(scope => {
          const trimmedScope = scope.trim();
          if (trimmedScope) {
            allBusinessScopes.add(trimmedScope);
          }
        });
      }
    }

    // 检查商品的qCategory是否在允许的经营范围内
    if (!allBusinessScopes.has(qCategory)) {
      throw new CoolCommException(`无经营权限，该商品属于"${qCategory}"类别，您的经营范围为：${Array.from(allBusinessScopes).join('、')}`);
    }
  }

  /**
   * 添加到购物车
   */
  async addCart(userId: string, goodsId: string, count: number = 1) {
    // 检查商品是否存在
    const goodsInfo = await this.goodsInfoEntity.findOne({
      where: {
        goodsId: goodsId,
      },
    });
    if (!goodsInfo) {
      throw new CoolCommException('商品不存在');
    }

    // 检查用户经营权限
    await this.checkBusinessPermission(userId, goodsInfo.gCategory);

    // 获取实时库存和价格
    console.log('goodsId', goodsId);
    console.log('userId', userId);
    const realTimeInfo = await this.getGoodsBalanceAndPrice(goodsId, userId);
    console.log('realTimeInfo', realTimeInfo);
    if (!realTimeInfo) {
      throw new CoolCommException('无法获取商品实时信息');
    }

    // 检查实时库存
    if (count > realTimeInfo.stornum) {
      throw new CoolCommException('库存不足');
    }

    // 如果实时价格与商品表中的价格不同，更新商品表
    if (realTimeInfo.saletaxp !== goodsInfo.price) {
      const updateData = {
        price: realTimeInfo.saletaxp
      };
      await this.goodsInfoEntity.update(goodsInfo.id, updateData);
      goodsInfo.price = realTimeInfo.saletaxp;
    }

    // 检查是否已在购物车中
    const exist = await this.orderCartEntity.findOne({
      where: {
        userId,
        goodsId,
      },
    });

    if (exist) {
      // 更新数量
      const newCount = exist.count + count;
      if (newCount > realTimeInfo.stornum) {
        throw new CoolCommException('库存不足');
      }
      await this.orderCartEntity.update(exist.id, {
        count: newCount,
        goodsInfo: {
          ...exist.goodsInfo,
          price: realTimeInfo.saletaxp
        }
      });
    } else {
      // 新增
      await this.orderCartEntity.insert({
        userId,
        goodsId,
        count,
        goodsInfo,
      });
    }
  }

  /**
   * 更新购物车商品数量
   */
  async updateCount(userId: string, id: number, count: number) {
    const cart = await this.orderCartEntity.findOne({
      where: {
        id,
        userId,
      },
    });

    if (!cart) {
      throw new CoolCommException('购物车商品不存在');
    }

    
    // 获取实时库存和价格
    const realTimeInfo = await this.getGoodsBalanceAndPrice(cart.goodsId.toString(), userId.toString());
    if (!realTimeInfo) {
      throw new CoolCommException('无法获取商品实时信息');
    }

    // 检查库存
    if (count > realTimeInfo.stornum) {
      throw new CoolCommException('库存不足');
    }

    await this.orderCartEntity.update(id, { count });
  }

  /**
   * 删除购物车商品
   */
  async remove(userId: string, ids: number[]) {
    await this.orderCartEntity.delete({
      userId,
      id: In(ids),
    });
  }

  /**
   * 清空购物车
   */
  async clear(userId: string) {
    await this.orderCartEntity.delete({ userId });
  }

  /**
   * 购物车列表
   */
  async listCart(userId: string) {
    return this.orderCartEntity.find({
      where: { userId },
      order: { createTime: 'DESC' },
    });
  }

  /**
   * 转换为订单商品
   */
  async toOrderGoods(userId: string, cartIds: number[]): Promise<OrderGoodsEntity[]> {
    const carts = await this.orderCartEntity.findBy({
      id: In(cartIds),
      userId,
    });

    if (!carts || carts.length === 0) {
      throw new CoolCommException('购物车为空');
    }
    const goodsList = await this.goodsInfoEntity.findBy({ goodsId: In(carts.map(cart => cart.goodsId)) });

    return carts.map(cart => {
      const orderGoods = new OrderGoodsEntity();
      const goodsInfo = goodsList.find(goods => goods.goodsId === cart.goodsId);
      orderGoods.goodsId = cart.goodsId;
      orderGoods.count = cart.count;
      orderGoods.price = goodsInfo.price;
      orderGoods.goodsInfo = goodsInfo;
      orderGoods.count = cart.count;
      return orderGoods;
    });
  }
} 